package edu.ubb.remeye.logging.aspect;

import org.apache.mina.core.session.IoSession;

import edu.ubb.remeye.communication.message.Message;
import edu.ubb.remeye.encodings.EncodingType;
import edu.ubb.remeye.exception.DESSecurityException;
import edu.ubb.remeye.exception.ImageEncodingException;
import edu.ubb.remeye.exception.InaccessibleServiceException;
import edu.ubb.remeye.exception.OSGIBundleInstallationException;
import edu.ubb.remeye.exception.OSGIFrameworkStartException;
import edu.ubb.remeye.exception.OSGIFrameworkStopException;
import edu.ubb.remeye.exception.ScreenCaptureException;
import edu.ubb.remeye.exception.SettingsLoadingException;
import edu.ubb.remeye.exception.SettingsSavingException;
import edu.ubb.remeye.logging.RemEyeLogger;
import edu.ubb.remeye.security.ResultType;
import edu.ubb.remeye.security.SecurityType;
import edu.ubb.remeye.server.communication.handler.ServerStateHandler.ServerContext;
import edu.ubb.remeye.server.settings.ServerSetter;

/**
 * Server logging aspect.
 * 
 * @author Andrew Ianicicau
 *
 */
public aspect ServerLogging {

	///////////////////////////////////////////////////////////////////////////////////
	////		METHODS - ServerLogging
	///////////////////////////////////////////////////////////////////////////////////
	
	/**
	 * Server started pointcut.
	 */
	private pointcut serverStarted():
		withincode(* edu.ubb.remeye.server.Server.startServer()) && set(boolean *.serverRunning);
	
	/**
	 * Server started logging advice.
	 */
	after(): serverStarted() {
		int port = ServerSetter.getInstance().getPort();
		RemEyeLogger.info(null, "SERVER[STARTING]: started");
		RemEyeLogger.info(null, "SERVER[RUNNING]: waiting for connections on port " + port);
	}
	
	/**
	 * Server stopped pointcut.
	 */
	private pointcut serverStopped():
		withincode(* edu.ubb.remeye.server.Server.stopServer()) && set(boolean *.serverRunning);
	
	/**
	 * Server stopped logging advice.
	 */
	after(): serverStopped() {
		int port = ServerSetter.getInstance().getPort();
		RemEyeLogger.info(null, "SERVER[STOPPING]: stopped listening on port " + port);
	}
	
	/**
	 * Session opened pointcut.
	 */
	private pointcut sessionOpened():
		execution(void *.sessionOpened(ServerContext, IoSession)) && within(edu.ubb.remeye.server.communication.handler.ServerStateHandler);
	
	/**
	 * Session opened logging advice.
	 * @param context
	 * @param session
	 */
	after(ServerContext context, IoSession session): sessionOpened() && args(context, session) {
		long id = context.getClientId();
		RemEyeLogger.info(null, "SERVER[SESSION OPENING][CLIENT ID = " + id + "]: session opened");
	}
	
	/**
	 * Session closed pointcut.
	 */
	private pointcut sessionClosed():
		execution(void *.sessionClosed(ServerContext, IoSession)) && within(edu.ubb.remeye.server.communication.handler.ServerStateHandler);
	
	/**
	 *  Session closed logging advice.
	 * @param context
	 * @param session
	 */
	after(ServerContext context, IoSession session): sessionClosed() && args(context, session) {
		long id = context.getClientId();
		RemEyeLogger.info(null, "SERVER[SESSION CLOSING][CLIENT ID = " + id + "]: session closed");
	}
	
	/**
	 * Session timeout pointcut.
	 */
	private pointcut timeout():
		execution(* *.timeout(..)) && within(edu.ubb.remeye.server.communication.handler.ServerStateHandler);
	
	/**
	 * Session timeout logging advice.
	 */
	after(ServerContext context, IoSession session): timeout() && args(context, session) {
		long id = context.getClientId();
		RemEyeLogger.info(null, "CLIENT[SESSION TIMEOUT][CLIENT ID = " + id + "]: no activity caused session timeout");
	}
	
	/**
	 * Setting security pointcut.
	 */
	private pointcut securitySet():
		withincode(void *.setSecurity(ServerContext, IoSession, Message));
	
	/**
	 * Setting security logging advice.
	 * @param message
	 * @param context
	 */
	after(Message message, ServerContext context): securitySet() && args(message, context) {
		long id = context.getClientId();
		SecurityType type = context.getSecurity();
		RemEyeLogger.info(null, "SERVER[SESSION RUNNING][CLIENT ID = " + id + "]: security set to " + type);
	}
	
	/**
	 * Starting authentication pointcut.
	 */
	private pointcut authenticationStarted():
		within(edu.ubb.remeye.server.communication.handler.ServerStateHandler) && call(void *.startAuthentication(ServerContext, IoSession));
	
	/**
	 * Starting authentication logging advice.
	 * @param context
	 * @param session
	 */
	after(ServerContext context, IoSession session): authenticationStarted() && args(context, session) {
		long id = context.getClientId();
		RemEyeLogger.info(null, "SERVER[SESSION RUNNING][CLIENT ID = " + id + "]: authentication started");
	}
	
	/**
	 * Getting authentication result pointcut.
	 */
	private pointcut authenticationResult():
		call(boolean *.getAuthenticationResult(IoSession));
	
	/**
	 * Getting authentication result logging advice.
	 * @param session
	 * @param result
	 */
	after(IoSession session) returning(boolean result): authenticationResult() && args(session) {
		long id = session.getId();
		ResultType res;
		if(result)
			res = ResultType.SUCCEEDED;
		else
			res = ResultType.FAILED;
		RemEyeLogger.info(null, "SERVER[SESSION RUNNING][CLIENT ID = " + id + "]: authentication " + res);
	}
	
	/**
	 * Setting encoding pointcut.
	 */
	private pointcut setEncoding():
		withincode(* *.setEncoding(..));
	
	/**
	 * Setting encoding logging advice.
	 * @param context
	 * @param message
	 * @param selected
	 */
	after(ServerContext context, Message message) returning (EncodingType selected): setEncoding() && args(context, message){
		long id = context.getClientId();
		RemEyeLogger.info(null, "SERVER[SESSION RUNNING][CLIENT ID = " + id + "]: encoding set to " + selected);
	}
	
	/**
	 * Setting control pointcut.
	 */
	private pointcut setControl():
		withincode(* *.controlRequest(..));
	
	/**
	 * Setting control logging advice.
	 * @param context
	 * @param control
	 */
	after(ServerContext context, boolean control): setControl() && args(context, control){
		long id = context.getClientId();
		RemEyeLogger.info(null, "SERVER[SESSION RUNNING][CLIENT ID = " + id + "]: client is in control: " + control);
	}
	
	/**
	 * Desktop is shared pointcut.
	 */
	private pointcut shared():
		execution(* *.controlRequest(..));
	
	/**
	 * Desktop is shared logging advice.
	 * @param context
	 * @param session
	 * @param message
	 */
	after(ServerContext context, IoSession session, Message message) returning(): shared() && args(context, session, message) {
		long id = context.getClientId();
		RemEyeLogger.info(null, "SERVER[SESSION RUNNING][CLIENT ID = " + id + "]: desktop shared to client");
	}
	
	/**
	 * ScreenCaptureException is thrown	logging advice.
	 * @param e
	 */
	before(ScreenCaptureException e): handler(ScreenCaptureException) && args(e) {
		RemEyeLogger.error(null, "SERVER[SESSION ERROR]: " + e.getMessage());
	}
	
	/**
	 * OSGIFrameworkStartException is thrown logging advice.	
	 * @param e
	 */
	before(OSGIFrameworkStartException e): handler(OSGIFrameworkStartException) && args(e) {
		RemEyeLogger.error(null, "SERVER[SESSION ERROR]: " + e.getMessage());
	}
	
	/**
	 * OSGIBundleInstallationException is thrown logging advice.	
	 * @param e
	 */
	before(OSGIBundleInstallationException e): handler(OSGIBundleInstallationException) && args(e) {
		RemEyeLogger.error(null, "SERVER[SESSION ERROR]: " + e.getMessage());
	}
	
	/**
	 * InaccessibleServiceException is thrown logging advice.	
	 * @param e
	 */
	before(InaccessibleServiceException e): handler(InaccessibleServiceException) && args(e) {
		RemEyeLogger.error(null, "SERVER[SESSION ERROR]: " + e.getMessage());
	}
	
	/**
	 * OSGIFrameworkStopException is thrown logging advice.
	 * @param e
	 */
	before(OSGIFrameworkStopException e): handler(OSGIFrameworkStopException) && args(e) {
		RemEyeLogger.error(null, "SERVER[SESSION ERROR]: " + e.getMessage());
	}
	
	/**
	 * ImageEncodingException is thrown logging advice.
	 * @param e
	 */
	before(ImageEncodingException e): handler(ImageEncodingException) && args(e) {
		RemEyeLogger.error(null, "SERVER[SESSION ERROR]: " + e.getMessage());
	}
	
	/**
	 * SettingsLoadingException is thrown logging advice.
	 * @param e
	 */
	before(SettingsLoadingException e): handler(SettingsLoadingException) && args(e) && within(edu.ubb.remeye.server.settings.ServerSetter){
		RemEyeLogger.error(null, "SERVER[SESSION ERROR]: " + e.getMessage());
	}
	
	/**
	 * SettingsSavingException is thrown logging advice.
	 * @param e
	 */
	before(SettingsSavingException e): handler(SettingsSavingException) && args(e) && within(edu.ubb.remeye.server.settings.ServerSetter){
		RemEyeLogger.error(null, "SERVER[SESSION ERROR]: " + e.getMessage());
	}
	
	/**
	 * DESSecurityException is thrown logging advice.
	 * @param e
	 */
	before(DESSecurityException e): handler(DESSecurityException) && args(e) && within(edu.ubb.remeye.security.manager.vnc.ServerVNCAuthenticator){
		RemEyeLogger.error(null, "SERVER[SESSION ERROR]: " + e.getMessage());
	}
	
}
